package com.ming.multifunction.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ming.multifunction.common.ErrorCode;
import com.ming.multifunction.contant.UserConstant;
import com.ming.multifunction.exception.BusinessException;

import com.ming.multifunction.model.domain.User;
import com.ming.multifunction.model.request.UpdateUserRequest;
import com.ming.multifunction.model.request.UserRegisterRequest;
import com.ming.multifunction.model.vo.UserVO;
import com.ming.multifunction.service.UserService;
import com.ming.multifunction.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.ming.multifunction.contant.UserConstant.ADMIN_ROLE;
import static com.ming.multifunction.contant.UserConstant.USER_LOGIN_STATE;

/**
 * 用户服务实现类
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 盐值，混淆密码
     */
    private static final String SALT = "ming";

    /**
     * 用户登录
     *
     * @param registerRequest
     * @param request
     * @return
     */

    @Override
    public long doRegister(UserRegisterRequest registerRequest, HttpServletRequest request) {

        if (registerRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "注册信息不能为空");
        }


        String email = registerRequest.getEmail();
        String requestVerifyCode = registerRequest.getVerifyCode();
        String avataUrl = registerRequest.getAvatarUrl();
        Integer gender = registerRequest.getGender();
        Integer age = registerRequest.getAge();
        String school = registerRequest.getSchool();
        String username = registerRequest.getUsername();

        String userPassword = registerRequest.getUserPassword();
        if (StringUtils.isAnyBlank(username, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号密码不能为空");
        }
        if (StringUtils.isBlank(email)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱不能为空");
        }
        if (StringUtils.isBlank(requestVerifyCode)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"验证码不能为空");
        }

        if (username.length() < 4 ) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能小于4");
        }
        if (username.length() > 12) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能大于12");
        }
        if ( userPassword.length() < 6){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能少于6个字符");
        }
        if ((userPassword.length()>12)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能大于12");
        }

        if (school.length()>20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"学校名称长度不能大于20个字符");
        }

        String regex = "^([A-Za-z0-9_\\-\\.\\u4e00-\\u9fa5])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,8})$";
        Pattern pattern = Pattern.compile(regex);

        Matcher matcher = pattern.matcher(email);
        boolean isValid = matcher.matches();

        if (!isValid) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请填写有效的邮箱");
        }

        if (StringUtils.isBlank(requestVerifyCode)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码不能为空");
        }

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername, username);
        long count = this.count(lambdaQueryWrapper);
        if (count >= 1) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户名已存在");
        }

        String verifyCode = (String) request.getSession().getAttribute("verifyCode");

        if (!verifyCode.equals(requestVerifyCode)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码不正确");
        }

        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());



        User user = new User();
        user.setUserRole(UserConstant.DEFAULT_ROLE);
        user.setEmail(email);
        user.setUserPassword(encryptPassword);
        user.setGender(gender);
        user.setUsername(username);
        user.setAge(age);
        user.setSchool(school);
        user.setAvatarUrl(avataUrl);

        boolean isSaved = this.save(user);
        if (!isSaved) {
            return -1;
        }

        return user.getId();
    }


    /**
     * 验证码
     * @param request
     * @return
     */
    @Override
    public String randomCode(HttpServletRequest request) {

        Random random = new Random();
        String verifyCode = "";
        for (int i = 0; i < 4; i++) {
            verifyCode += random.nextInt(9);
        }
        request.getSession().setAttribute("verifyCode", verifyCode);

        return verifyCode;
    }

    /**
     * 搜索用户
     * @param searchText
     * @return
     */
    @Override
    public List<UserVO> searchUser(String searchText) {

        if (StringUtils.isBlank(searchText)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"搜索关键词不能为空!");
        }

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(User::getUsername,searchText)
                .or()
                .like(User::getSchool,searchText)
                .or()
                .like(User::getEmail,searchText);

        List<User> list = this.list(wrapper);

        if (CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }

        ArrayList<UserVO> arrayList = new ArrayList<>();
        for (User user:list){
            if (user==null){
                continue;
            }

            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user,userVO);
            arrayList.add(userVO);
        }


        return arrayList;
    }

    /**
     * 用户登录
     *
     * @param username  用户账户
     * @param userPassword 用户密码
     * @param request
     * @return 脱敏后的用户信息
     */
    @Override
    public User userLogin(String username, String userPassword, HttpServletRequest request) {
        // 1. 校验
        /*if (StringUtils.isAnyBlank(username, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"")
        }*/

        if (StringUtils.isBlank(username)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号不能为空");
        }
        if (StringUtils.isBlank(userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能为空");
        }

        /*if (username.length() < 4) {
            return null;
        }
        if (userPassword.length() < 6) {
            return null;
        }*/
        // 账户不能包含特殊字符
       /* String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()) {
            return null;
        }*/
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        // 查询用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        queryWrapper.eq("userPassword", encryptPassword);
        User user = userMapper.selectOne(queryWrapper);
        // 用户不存在
        if (user == null) {
            log.info("user login failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号或密码不正确！");
        }

        String id = request.getSession().getId();
        log.info(id);

    /*    if (stringRedisTemplate.hasKey(username)&& !id.equals(stringRedisTemplate.opsForValue().get(username))){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"你已经有账号登录");
        }
        stringRedisTemplate.opsForValue().set(username,id);*/



        // 3. 用户脱敏
        User safetyUser = getSafetyUser(user);
        // 4. 记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, safetyUser);
        return safetyUser;
    }

    /**
     * 用户脱敏
     *
     * @param originUser
     * @return
     */
    @Override
    public User getSafetyUser(User originUser) {
        if (originUser == null) {
            return null;
        }
        User safetyUser = new User();
        safetyUser.setId(originUser.getId());
        safetyUser.setUsername(originUser.getUsername());
        safetyUser.setAge(originUser.getAge());
        safetyUser.setAvatarUrl(originUser.getAvatarUrl());
        safetyUser.setGender(originUser.getGender());
        safetyUser.setSchool(originUser.getSchool());
        safetyUser.setEmail(originUser.getEmail());
        safetyUser.setCreateTime(originUser.getCreateTime());
        safetyUser.setUserRole(originUser.getUserRole());

        safetyUser.setCreateTime(originUser.getCreateTime());


        return safetyUser;
    }

    /**
     * 用户注销
     * @param request
     */
    @Override
    public int userLogout(HttpServletRequest request) {
        // 移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return 1;
    }


    /**
     * 更新用户
     *
     * @param user
     * @param loginUser
     * @return
     */
    @Override
    public int updateUser(UpdateUserRequest user, User loginUser) {

        long id = user.getId();
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不存在");
        }

        if (!isAdmin(loginUser) && id != loginUser.getId()) {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }

        User oldUser = userMapper.selectById(id);

        if (oldUser == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR,"用户不存在");
        }


        String avataUrl = user.getAvatarUrl();
        Integer gender = user.getGender();
        Integer age = user.getAge();
        String school = user.getSchool();

        String username = user.getUsername();
        String userPassword = user.getUserPassword();
        if (StringUtils.isAnyBlank(username, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号密码不能为空");
        }
        String email = user.getEmail();
        if (StringUtils.isBlank(email)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱不能为空");
        }

        if (username.length() < 4 ) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能小于4");
        }
        if (username.length() > 12) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能大于12");
        }
        if ( userPassword.length() < 6){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能少于6个字符");
        }
        if ((userPassword.length()>12)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能大于12");
        }

        if (school.length()>20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"学校名称长度不能大于20个字符");
        }

        if (StringUtils.isBlank(avataUrl)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户头像不能为空");
        }

        String regex = "^([A-Za-z0-9_\\-\\.\\u4e00-\\u9fa5])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,8})$";
        Pattern pattern = Pattern.compile(regex);

        Matcher matcher = pattern.matcher(email);
        boolean isValid = matcher.matches();

        if (!isValid) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请填写有效的邮箱");
        }

        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        User newUser = new User();
        newUser.setId(user.getId());
        newUser.setUserRole(UserConstant.DEFAULT_ROLE);
        newUser.setEmail(email);
        newUser.setUserPassword(encryptPassword);
        newUser.setGender(gender);
        newUser.setUsername(username);
        newUser.setAge(age);
        newUser.setSchool(school);
        newUser.setAvatarUrl(avataUrl);
        newUser.setUpdateTime(new Date());
        boolean update = this.updateById(newUser);

        if (!update) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"更新失败");
        }

        return userMapper.updateById(newUser);
    }


    /**
     * 是否为管理员
     *
     * @param request
     * @return
     */
    @Override
    public boolean isAdmin(HttpServletRequest request) {
        // 仅管理员可查询
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) userObj;
        return user != null && user.getUserRole() == ADMIN_ROLE;
    }

    /**
     * 是否为管理员
     *
     * @param loginUser
     * @return
     */
    @Override
    public boolean isAdmin(User loginUser) {
        // 仅管理员可查询
        return loginUser != null && loginUser.getUserRole() == ADMIN_ROLE;
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {

        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Object user = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        return (User) user;
    }


}

